package com.yunwaikeji.gy_tool_library.mvvm.net;

import android.text.TextUtils;

import com.yunwaikeji.gy_tool_library.info.GYHttpInfo;
import com.yunwaikeji.gy_tool_library.utils.GYLogUtils;

import java.nio.charset.StandardCharsets;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class GYRetrofitClient implements GYHttpInfo {
    private static GYRetrofitClient gyRetrofitClient;
    private String baseUrl;//地址
    private Retrofit retrofit;

    public static GYRetrofitClient getInstance() {
        if (gyRetrofitClient == null) {
            gyRetrofitClient = new GYRetrofitClient();
        }
        return gyRetrofitClient;
    }

    public <T> T getService(Class<T> tClass) {
        if (retrofit == null) {
            GYLogUtils.printError(this, "未初始化");
        }
        return retrofit.create(tClass);
    }

    private RequestResult requestResult;

    public interface RequestResult {
        Request requestResult(Request request);
    }

    public GYRetrofitClient setRequestResult(RequestResult requestResult) {
        this.requestResult = requestResult;
        return this;
    }

    private ResponseResult responseResult;

    public interface ResponseResult {
        Response responseResult(Response response);
    }

    public GYRetrofitClient setResponseResult(ResponseResult responseResult) {
        this.responseResult = responseResult;
        return this;
    }

    public OkHttpClientBuilder okHttpClientBuilder;

    public interface OkHttpClientBuilder {
        OkHttpClient.Builder okHttpClientBuilder(OkHttpClient.Builder builder);
    }

    public GYRetrofitClient setOkHttpClientBuilder(OkHttpClientBuilder okHttpClientBuilder) {
        this.okHttpClientBuilder = okHttpClientBuilder;
        return this;
    }

    private Interceptor getRequestIntercept() {
        return chain -> {
            Request request;
            if (requestResult == null) {
                request = chain.request();
            } else {
                request = requestResult.requestResult(chain.request());
                if (request == null) {
                    request = chain.request();
                }
            }
            StringBuilder contentBuilder = getContentBuilder("网络请求Request", request);
            if (request.headers().names().size() > 0) {
                contentBuilder.append("\n----------Header开始----------");
                for (String name : request.headers().names()) {
                    contentBuilder.append("\n").append(name).append(":").append(request.header(name));
                }
                contentBuilder.append("\n----------Header结束----------");
            }
            if (request.url().queryParameterNames().size() > 0) {
                contentBuilder.append("\n----------Query开始----------");
                for (String name : request.url().queryParameterNames()) {
                    contentBuilder.append("\n").append(name).append(":").append(request.url().queryParameter(name));
                }
                contentBuilder.append("\n----------Query结束----------");
            }
            String bodyString = "";
            RequestBody requestBody = request.body();
            if (requestBody != null) {
                Buffer buffer = new Buffer();
                requestBody.writeTo(buffer);
                contentBuilder.append("\n----------Body开始----------");
                bodyString = buffer.readString(StandardCharsets.UTF_8);
            }
            GYLogUtils.printJson("网络请求Request", contentBuilder.toString(), bodyString, "----------Body结束----------");
            return chain.proceed(request);
        };
    }

    private Interceptor getResponseIntercept() {
        return chain -> {
            Request request = chain.request();
            StringBuilder contentBuilder = getContentBuilder("网络响应Response", request);
            contentBuilder.append("\n----------Body开始----------");
            Response response = chain.proceed(request);
            ResponseBody responseBody = response.body();
            String bodyString = "";
            if (responseBody != null) {
                bodyString = responseBody.string();
            }
            GYLogUtils.printJson("网络响应Response", contentBuilder.toString(), bodyString, "----------Body结束----------");
            if (responseResult == null) {
                return chain.proceed(request);
            } else {
                Response response1 = responseResult.responseResult(chain.proceed(request));
                if (response1 == null) {
                    return chain.proceed(request);
                } else {
                    return response1;
                }
            }
        };
    }

    private OkHttpClient getOkHttpClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .addInterceptor(getRequestIntercept())
                .addInterceptor(getResponseIntercept());
        if (okHttpClientBuilder == null) {
            return builder.build();
        } else {
            return okHttpClientBuilder.okHttpClientBuilder(builder).build();
        }
    }

    public GYRetrofitClient setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
        return this;
    }

    public void finish() {
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(getOkHttpClient())
                .build();
    }

    private StringBuilder getContentBuilder(String title, Request request) {
        StringBuilder contentBuilder = new StringBuilder();
        if (!TextUtils.isEmpty(title)) {
            contentBuilder.append(title).append("\n");
        }
        contentBuilder
                .append("地址url：").append(baseUrl).append(request.url().url().getPath())
                .append("\n请求方式RequestMethod：").append(request.method());
        return contentBuilder;
    }
}
